package online.flowerinsnow.minecraft.bukkit.manhunt.config;


import online.flowerinsnow.minecraft.bukkit.manhunt.core.hunter.OnDead;
import org.bukkit.Bukkit;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.configuration.file.YamlConfiguration;
import online.flowerinsnow.minecraft.bukkit.manhunt.Manhunt;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;

public class ManhuntConfiguration {
    private static FileConfiguration config;
    private static final Map<String, Field> entries = new HashMap<>();

    static {
        checkClass(null, ManhuntConfiguration.class);
    }

    private static void checkClass(String parent, Class<?> cls) {
        checkFields(parent, cls);
        checkInnerClass(parent, cls);
    }

    private static void checkFields(String parent, Class<?> cls) {
        for (Field field : cls.getDeclaredFields()) {
            field.setAccessible(true);
            if (field.isAnnotationPresent(ConfigEntry.class)) {
                ConfigEntry annotation = field.getAnnotation(ConfigEntry.class);
                String key;
                if (parent == null) key = annotation.value();
                else key = parent + "." + annotation.value();
                entries.put(key, field);
            }
        }
    }

    private static void checkInnerClass(String parent, Class<?> cls) {
        for (Class<?> innerClass : cls.getDeclaredClasses()) {
            if (innerClass.isAnnotationPresent(ConfigCategory.class)) {
                ConfigCategory annotation = innerClass.getAnnotation(ConfigCategory.class);
                String key;
                if (parent == null) {
                    key = annotation.value();
                } else {
                    key = parent + "." + annotation.value();
                }
                checkClass(key, innerClass);
            }
        }
    }


    @ConfigCategory("runner")
    public static class Runner {
        @ConfigEntry("ondead")
        public static online.flowerinsnow.minecraft.bukkit.manhunt.core.runner.OnDead ondead;
    }

    @ConfigCategory("hunter")
    public static class Hunter {
        @ConfigEntry("ondead")
        public static OnDead ondead;
    }
    @ConfigEntry("gameworld")
    public static String gameworld;
    @ConfigEntry("specspec")
    public static boolean specSpec;

    @ConfigCategory("fun")
    public static class Fun {
        @ConfigEntry("skull")
        public static boolean skull;
        @ConfigEntry("fastmine")
        public static boolean fastMine;

        @ConfigEntry("specialmobs")
        public static boolean specialmobs;

        @ConfigCategory("moremobs")
        public static class MoreMobs {
            @ConfigEntry("healirongolem")
            public static boolean healIronGolem;
        }
    }

    public static void load() {
        Manhunt.getInstance().reloadConfig();
        ManhuntConfiguration.config = Manhunt.getInstance().getConfig();
        saveDefault();
        entries.keySet().forEach(k -> loadField(k, entries.get(k)));
    }

    private static void loadField(String key, Field field) {
        Class<?> type = field.getType();
        try {
            if (Integer.TYPE.equals(type)) {
                field.set(null, config.getInt(key));
            } else if (Long.TYPE.equals(type)) {
                field.set(null, config.getLong(key));
            } else if (Double.TYPE.equals(type)) {
                field.set(null, config.getDouble(key));
            } else if (String.class.equals(type)) {
                field.set(null, config.getString(key));
            } else if (Boolean.class.equals(type)) {
                field.set(null, config.getBoolean(key));
            } else if (Enum.class.equals(type.getSuperclass())) {
                String name = config.getString(key);
                if (name == null) {
                    Manhunt.getInstance().getLogger().severe("错误的配置: " + key + " (未找到对应的枚举成员)");
                    Bukkit.getPluginManager().disablePlugin(Manhunt.getInstance());
                    return;
                }
                field.set(null, type.getField(name).get(null));
            }
        } catch (IllegalAccessException | NoSuchFieldException e) {
            e.printStackTrace();
        }
    }

    public static void save() {
        try {
            ManhuntConfiguration.config.save(new File(Manhunt.getInstance().getDataFolder(), "config.yml"));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void saveDefault() {
        //noinspection ConstantConditions
        try (InputStream in = Manhunt.getInstance().getResource("config.yml");
             InputStreamReader isr = new InputStreamReader(in)) {
            YamlConfiguration config = YamlConfiguration.loadConfiguration(isr);
            ManhuntConfiguration.config.setDefaults(config);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
